Index


RISC World

MFCalc

Martin Carradus takes us through his multi function calculator

!MFCalc performs numerical calculations on expressions typed into its Input slot when the 'Calculate' button is clicked upon. The slot may be cleared out either by typing Control with 'U', or by clicking on the 'Clear Entry' button.

The following can be typed into the 'Input' slot:-

Remarks
Remarks begin with '/*' and end with '*/', and are totally ignored by !MFCalc.

Numerics
These are of Five types:

  • Integers: e.g. 1234
  • Exponented Integers: e.g. 1234E1 or 1234e+2
  • Hexadecimal constants, which begin with '&', '&h' or '&H': e.g. &H1ab or &HADD. They are case insensitive.
  • Octal constants, which begin with '&o' or '&O': e.g. &O0137
  • Floating constants: They always have a decimal point in them and can also be exponented: e.g. .1234 or 1.25 or 2.3456e-6 or 0.001E+5

Variables
A named storage location containing a numeric value.

These always begin with an alpha character or underscore, then continue with any alphanumeric or underscore. These are case sensitive and become available with the value zero wherever they are mentioned. Integer variables end with a '%', otherwise they are taken to be floating point, unless declared otherwise (see below). They also can be of any length up to the 256 character limit of the Input slot.

Examples: 'a' or 'A%' or '_HELLO' or 'var1%' or 'non_zero'.

Assignment of Variables
This is simply done by typing the variables name then '=' then some numeric expression to the right of that, which in turn may contain variable names. e.g. num0=1.0 or A%=B%+6 or _hello=_goodbye

These statements may optionally be preceded by the key word 'LET', in upper or lower case.

e.g. LET a=0.0 or let no%=2

Note that if you assign an integer variable a floating value, then it will be truncated to an integer.

e.g. let a%=-2.5 gives a% the value -2

Multiple Assignments
Simply concatenate the assignments together with a colon between.

Example: a%=b%*6:let c%=a%+4:d=c%^2

Operators

You have already seen some of these above, they are:

  • Addition and Subtraction: '+' and '-' e.g. 1+2 or 4.0-2.0
  • You may also negate expressions: e.g. a%=-b%
  • Multiplication and Division: '*' and '/' e.g. 6*7 or 1.0/2.0

!MFCalc will complain about division by zero by outputting a comment if this happens.

Integer Division: 'div' or 'DIV', performs the division and then truncates it to an integer. Also complains about division by zero.

e.g. '5.0 div 2.0' gives the value '2'.

Modular Arithmetic: 'mod' or 'MOD', gives the remainder upon division.

e.g. 5 MOD 2 gives the value '1'. Complains about MOD with respect to zero.

Lastly raising a% to the power b% is denoted by 'a%^b%', and, unlike the rest binds to the right, so 'a%^b%^c%' is taken as 'a%^(b%^c%)'.

So 3^1^2 is 3, not 9.

!MFCalc complains about raising zero to a zero or negative power.

Also beware of raising negative quantities to fractional powers.

As you can see, these expressions may be bracketed, but otherwise the precedence of these operators is in reverse order to the list above, going from performing powers at highest precedence, to addition and subtraction at lowest precedence.

In all this, if !MFCalc can't make sense of the input line, it outputs a 'Syntax Error' comment.

Combinations

The number of ways of picking r objects from n without regard to the order of the objects�is usually denoted by:-

        n
           C
               r

The 'combination' of r objects from n.

e.g. The number of ways of picking 1 object from 5 is 5, but the number of ways of picking 2 objects from 5 is 10.

The operator in !MFCalc you use is 'NCR' or 'ncr', so

'5 ncr 1' yields a value of 5, and '5 ncr 2' yields a value of 10.

You may use floating values, but !MFCalc complains if they have any fractional places. !MFcalc also complains if either of the values supplied is negative, or if the second value exceeds the first.

If you exceed several hundred for either of the arguments, you will get a message about 'Stack Overflow', as recursion is employed.

Lastly NCR binds the least of all the operators, so all calculations on both sides are performed first before the combination is taken.

e.g. '6-1 ncr 3-1' will give you the value of '5 ncr 2'.

NB NCR is not associative, so !MFcalc will error multiple NCRs in one expression e.g. '12 NCR 2 NCR 2' will cause a syntax error.

Minimum and Maximum of Values

The operators 'MIN' and 'min' or 'MAX' and 'max' between two expressions give the minimum or maximum of the two values e.g.

'2 min 1' gives a value of 1, but '2 max 1' gives a value of 2

These operators bind more tightly than addition or subtraction, but less than multiplication and division or any higher operator, so,

'2 min 1 + 3 min 2', will give the sum '1 + 2' giving 3, but '2*6 min 3*8' will produce '12 min 24', giving 12.

Also they are left associative, so combinations of 'min' and 'max' are obeyed from left to right e.g.

'2 max 1 min 4' becomes '2 min 4', which becomes 2

You will note that you can obtain the minimum or maximum of more than two values by simply concatenating them between the same operator e.g.

'x% min y% min z%' gives the minimum of x% and y% and z% and 'x% max y% max z%' gives the maximum of x% and y% and z%.

Both 'min' and 'max' attempt to keep the resulting value as an integer whenever possible e.g.

'2.0 max 4.0' will produce the integer value of '4', not '4.0', but '2 max 4.7' will produce the floating value '4.7'

Lowest Common Multiple (LCM) and Greatest Common Divisor (GCD)

The Greatest Common Divisor of two Numbers is the largest number less than or equal to them that divides into both numbers exactly.

e.g. '6 gcd 21' gives 3, as 6=3*2 and 21=3*7, so 3 is the largest common factor. !MFCalc uses a method called 'Euclid's Algorithm' to obtain this number. If two numbers share no common factor greater than or equal to two, then their GCD is one. This is true particularly when both are prime.

The Lowest Common Multiple of two numbers is the lowest number that shares the factors of both numbers.

e.g. '6 lcm 21' gives 42=3*2*7, as 6=3*2 and 21=3*7, 42 is the smallest number that shares the factors of both numbers.

Note that that the LCM times the GCD of a and b is equal to (a times b) for all a and b.

LCM and GCD both complain if either of the supplied numbers is zero or negative or fractional. Both, also, always give out integer results. (No decimal places shown.)

The operators 'gcd' and 'lcm' are on a par with 'min' and 'max' in terms of priority - higher than addition or subtraction, but lower than multiplication or division or raising to powers.

e.g. '3*2 gcd 3*7', will give the answer '3', as the multiplication is performed first before the 'gcd'.

These operators are also associative, so you may obtain the LCM of x%, y% and z%, by typing 'x% lcm y% lcm z%' in the 'Input:' slot and clicking on 'Calculate'. If there is no operator of a higher priority,'lcm' and 'gcd' are obeyed from left to right.

Mathematical Functions

There are twenty one of these available, and if the arguments are out of range, !MFCalc complains. These functions need not have the input expression in brackets and bind more tightly than any of the operators. With trigonometric functions there are buttons on the 'SetUp' panel to select calculation in degrees, radians or grads.

  • 'ABS' or 'abs' - Absolute positive value without the sign.
  • 'ACS' or 'acs' - Arccosine.
  • 'ASN' or 'asn' - Arcsine.
  • 'ATN' or 'atn' - Arctangent.
  • 'COS' or 'cos' - Cosine of the Angle given.
  • 'COSH' or 'cosh' - Hyperbolic cosine.
  • 'EXP' or 'exp' - Raising e to the given power.
  • 'FRAC' or 'frac' - Fractional part of the given number. Negative if the number is negative.
  • 'INT' or 'int' - Truncate to the integer below.
  • 'FIX' or 'fix' - Round to nearest integer. If negative, rounds down, if positive, rounds up.
  • 'LN' or 'ln' - Natural logarithm to base e.
  • 'LOG' or 'log' - Logarithm to base ten.
  • 'RND', 'rnd', "RAND", or "rand" - Gives out a random number in the range 0 - 1 (inclusive). Does not take in any value as an argument.
  • 'SGN' or 'sgn' - The 'sign' of the number, -1 if negative, 0 if zero, +1 if positive.
  • 'SIN' or 'sin' - Sine of supplied angle.
  • 'SINH' or 'sinh' - Hyperbolic sine.
  • 'SQR' or 'sqr' - Square root, complains if supplied number is negative. Additionally, 'SQRT' or 'sqrt' will also be accepted.
  • 'TAN' or 'tan' - Tangent of supplied angle.
  • 'TANH' or 'tanh' - Hyperbolic tangent.
  • 'CBR' or 'cbr' - Cube root, turns negative if supplied number is negative. Additionally, 'CBRT' or 'cbrt' will also be accepted.
  • 'LNFACT' or 'lnfact' - The natural logarithm of the factorial of the supplied argument. The factorial of a number is the product of the number with all the ones below it down to 1, so 3 factorial is 3.2.1=6 and 4 factorial is 4.3.2.1=24. The natural logarithm is taken because factorials grow large very quickly, so the logarithm slows this process down and stops numeric overflow at higher values. As with 'ncr', very large arguments cause a 'Stack Overflow' message.

In addition, the key word 'PI' or 'pi' in a calculation gives out the numeric value of the trigonometric constant pi.

All of these function names are reserved words and should not be used for variable names.

As already mentioned, these functions bind more tightly than any other operator, so, for example, the value of 'SIN 90 +2' is 3.0, not the Sine of 92, when in degree mode. Note that 'SIN' is separated from 90 so that the reserved word 'SIN' can be recognised. If you had typed 'SIN90+2', a variable name 'SIN90' would be created, given a floating value of 0.0 and 2.0 added, so 2.0 would be output. Note, also, that if you had really wanted the Sine of 90+2, you should have used brackets and put 'SIN(90+2)'.

The Form of the Calculated Value

The form (integer or floating point (double precision)) of the expression being calculated is always at the level of the highest operand, so, 2+3 gives an integer value of 5, and 5/2 gives an integer value of 2, but 2+3.0 gives a floating value of 5.0, and 5/2.0 gives a floating value of 2.5. If you had meant an integer divide to be performed, then you should have used 'DIV', i.e. '5 DIV 2.0' gives out an integer value of 2.

Getting back the Last Calculated Value

The special variable 'ANS' or 'ans' is assigned the value of the last calculation. If this is an integer, ANS takes an integer value, if this is a floating value, ANS is floating, otherwise ANS starts with an integer value of 0. Like any other variable, ANS may be assigned a value. e.g. let ANS=2.5 , but it will not appear in the list produced by the LIST instruction (see below).

Declarations

Additionally you may declare variables to be integer or floating (double precision) using the key words 'INTEGER' or 'DOUBLE' respectively followed by a�comma separated list of variable names of any type, either integer or float. You may also assign these variable names by using '='.

e.g.

INTEGER a, b, c=3

or

DOUBLE A%=1.2,D,e=2.71828

You may not concatenate these declarations.

PRIME Keyword

Prime numbers are not divisible by anything other than 1 and themselves. If a number is not prime, it can be represented as the product of primes and powers of primes less than itself, called factors. The number is said to be 'composite'.

'PRIME' or 'prime' followed by any expression will determine if the integer produced is a prime number. Complains if the number is fractional. If the number is negative, the sign is removed before prime determination. If the number is floating point, it is integerised, but complains if the result would be too large for an integer. Indicates if the number is zero or +1 or -1 or even. This is done in integer arithmetic, so !MFCalc may crash if the number is too large.

Gives the smallest factor if the number is not prime.

e.g. 'PRIME 2^31-1' will produce the REM '/* 2147483647 is Prime */'. 'PRIME 13*17' will produce the REM '/* 221 is not Prime, Factor 13 */'.

'PRIME' or 'prime' followed by an expression can also be put, separated by a colon, at the very end of a colon-separated list of assignments and 'input' statements (see below).

e.g. A 'Mersenne' prime is one of the form '2^n-1', so by repeating the line: 'input a%:prime 2^a%-1', using 'Entry Back' and 'Calculate', you may investigate for what values of a%, 2^a%-1 is prime.

Lastly, PRIME sets ANS to the value of the found lowest factor of the supplied expression, or to the value 1 if the expression is prime. So, for example, start with the line 'm%=1:ANS=1'. Then repeat the line: 'm%=m%*ANS:PRIME <expression>:/m%', where <expression>: is the expression you wish to factorise, and continue until you get a prime. You will then have found all the prime factors of <expression>:.

Getting Rid of all the Variables

The command 'CLEAR' or 'clear' will remove all the variables and start from scratch again.

Getting Rid of One Variable

The command 'CLEAR' or 'clear' followed by the variable name will cause the variable to be removed from the list of defined variable names.

e.g. CLEAR a%

A message indicates if the variable name was already undefined.

Checking the Variables Present

The single command 'LIST' or 'list' and clicking 'Calculate' will cause an alphabetical list of the variable names and values to appear in the Input Slot. After each line, press the Return (Enter) key and a new line appears, or a message indicating the end of the list. Pressing the Escape key at any time terminates the list and a message indicating that appears. A message also indicates when no variables have been defined. The list also shows if the variable has not been explicitly assigned a value. Also the form of representation of the assigned value in the list gives the variable's data type - it is represented as an integer without a decimal point if the variable is to be taken as holding an integer value - with a decimal point if it is a floating variable e.g. a variable with the a value of six would be listed with a value '6' if it was an integer variable, but '6.0' if it was a floating (double precision) variable.

The Field Length and Number of Decimal Places

Just type numeric values into the slots provided, then press the 'Enter' key (Return). !MFCalc requires that you press 'Enter' before these values are recognised. Clearing them out to nothing just leaves the values unaltered. !MFCalc complains if you try to make the field length less than the number of places, or the number of places more than the field length. Not available in hexadecimal or octal notation. Also the choice of representation in floating, exponential or general format is only available in decimal notation, not hex or octal.

The INPUT command

The key word 'INPUT' followed by a single variable name e.g. INPUT a% will cause a prompt REM of the form:- '/* Type a%, Enter or Escape */ to appear in the 'Input:' slot together with a red caret. Typing the value at the caret and pressing 'Enter' ('Return') will assign the variable a% with the typed literal. Pressing the 'Escape' key at this point leaves the variable unassigned with its default value of zero.

Note that !MFCalc will only accept literals e.g. 123, 2.31, &123, &o127, 1E2, 0.5e-04 or a single variable name at the prompt, not whole expressions. The only exception is that you may put a minus '-' sign in front.

Also Note pressing the 'Backspace' or 'Delete' key, if you make a mistake, will erase the mistaken entry, and assign the variable the new value on pressing 'Enter' ('Return'). Pressing the 'Escape' key, as mentioned above, aborts the current INPUT statement. In this case, no new value is assigned. This is useful if you do not wish to alter the value of an INPUT variable. If you use the cursor keys to move backwards and forwards in the 'Input:' slot, they will have no effect.

Inherited Unassignment: If you use INPUT and enter an unassigned variable name at the prompt, then the INPUT variable remains unassigned.

INPUT statements can be concatenated, so, you may put e.g.

INPUT a%:INPUT b%:INPUT c%

And !MFCalc will prompt for the value a%, then b%, then c%

The INPUT statement allows you to give your own prompt by supplying a double quoted character string, which is converted to your own REM before the prompt caret e.g. 'INPUT "Give Value"; a%' will give:

'/* Give Value */ followed by a prompt for the value. If you supply '/*' or '*/' in the quoted string, they are removed from the REM. If you require a double quote, supply "" within the string, which is converted to a " within your REM. The semi-colon afterwards, when supplied, suppresses a '?' from being added to the REM.

The PRINT Command

'PRINT' followed by any expression simply gives the value of the expression when the 'Calculate' button is clicked on. The advantage is that this command can occur after a colon at the end of any series of assignments or INPUTs e.g.

'INPUT a%:b%=1:INPUT c%:PRINT a%+b%+c%' will prompt for the values of a% and c% then give the value of a%+b%+c%. PRINT should only occur at the end of an 'Input:' line.

Similarly to INPUT, PRINT can be followed by a string of characters in double quotes before the expression. The string will be output as a comment before the value of the expression when 'Calculate' is clicked on. You may separate the string from the expression by a semi-colon, but it has no effect.

As described below, you may bring this line back and so perform a calculation many times over with different input values.

The 'Entry Back' and 'Entry Forward' Buttons

Every time you click on 'Calculate', the 'Input:' slot value is stored away on a stack. The 'Entry Back' button, when clicked, successively brings back previous 'Input:' lines into the 'Input:' slot. There is enough storage to hold up to twenty previous lines. When this is exceeded, the 'stack' shifts up, so lines more than twenty ago are lost.

The 'Entry Forward' button moves forward in time right up to the current line, reversing the effect of 'Entry Back'.

Neither of these buttons have any effect until you have entered several lines.

If you go back to a previous line, then enter a different line and click on 'Calculate', then immediately the entries forward in time from the chosen line are lost, but those previous in time to the chosen line can still be obtained by clicking on the 'Entry Back' button.

'Input:' Lines are not recorded in the memory stack if they are blank or they repeat the same calculation as the previous entry on the stack. This means you can repeat previous calculations without it affecting the previous line memory stack.

Lastly, the 'Clear Entries' button completely clears out the memory stack and all knowledge of any previous lines is lost. Remember to distinguish this from the 'Clear Entry' button, that just clears out the 'Input:' slot and has no effect on the memory stack.

The 'Save Entries' and 'Retrieve Entries' Buttons

The 'Save Entries' Button copies all the entries in the memory stack to an internal file, which can be brought back by clicking on the 'Retrieve Entries' Button, even after you have Quit the whole application. Both buttons give out a message indicating how many entries were Saved/Retrieved, but in the case of 'Retrieve Entries', Press the 'Enter' ('Return') key afterwards. The entry you will then see in the 'Input:' slot is the last one you were looking at when you Saved the Entries.

If you have a constant set of calculations you perform, this saves having to type them in time and again.

Getting Out of the Application

You may select 'Quit' from both the icon bar menu and the 'Help' menu to terminate the application. Selecting the 'Close' icon on the 'SetUp' panel simply removes the panel and does not clear any of the variable names, but typing 'QUIT' or 'quit' in the 'Input' slot and clicking 'Calculate' both removes the panel and clears the variable names. Lastly, typing 'EXIT' or 'exit' and clicking 'Calculate' completely terminates the application. In certain circumstances, the 'Escape' key has the same effect as 'QUIT'.

Bugs

1. It has been discovered that the value returned for the Sine of 90 degrees is marginally greater than one, so if you immediately perform an Arc Sine on this value, !MFCalc objects to the number input to Arc Sine being greater than one. i.e. ASN SIN 90 in degree mode produces an error message, not a return value of 90. The same is true of SIN -90. The same is not true of the COS of zero.

2. If the resulting value of integer arithmetic with '+', '-', '*' or '^' overflows the 32 bits used for its (signed) representation, then the calculation is converted to a floating one. The same is not true for floating calculations. If you wish to calculate with large numbers, then you could use floating arithmetic e.g. represent one hundred million as '100000000.0'. However, if any integer literal in a calculation exceeds about 8 digits, it is automatically converted so as to be taken as floating literal and the whole calculation is performed as a floating one anyway.

Integer '/', MOD or DIV are calculated in integer storage. If the numbers involved are large (roughly over 8 digits), it can cause integer overflow and !MFCalc crashes.

Also realise that even if the calculation is done in floating point format, because of the way the number is stored, only 16 - 17 significant digits can be held. If, for example, the result of the calculation exceeds 10^17, then only the first 16 - 17 digits will appear before the decimal point, the rest being zero.

3. For various reasons, it is best to perform repeated raising to powers (using '^') as all integer as all float (not mixed arithmetic).

e.g. 3 ^ 2 ^ 2 or 3.0 ^ 2.0 ^ 2.0, but not 3 ^ 2.0 ^ 2.0

However, with a single '^', any mixture of integer or float is acceptable. As mentioned above, if the two operands are integer, the result is an integer, but otherwise the result is floating.

Also beware of large numeric values (overflow) developing during repeated exponentiation. It can produce very odd output results, particularly when displaying in 'Floating' mode.

Reserved Words

A list of the reserved words (both in upper and lower case) used by !MFCalc follow. They should not be used as variable names. If you get an odd result or a syntax error, then you are probably using a reserved word in the wrong place, or think you are using one when you have typed it incorrectly or not separated it properly from other alphanumerics. Note the reserved words are either all upper case or all lower case and not any mixture:

"ABS", "ACS", "ANS", "ASN", "ATN", "CBR", "CBRT", "CLEAR", "COS", "COSH", "DIV", "DOUBLE", "EXIT", "EXP", "FIX", "FRAC", "GCD", "INPUT", "INT", "INTEGER", "LCM", "LET", "LIST", "LN", "LNFACT", "LOG", "MAX", "MIN", "MOD", "NCR", "PI", "PRIME", "PRINT", "QUIT", "RAND", "REM", "RND", "SGN", "SIN", "SINH", "SQR", "SQRT", "TAN", "TANH", "abs", "acs", "ans", "asn", "atn", "cbr", "cbrt", "clear", "cos", "cosh", "div", "double", "exit", "exp", "fix", "frac", "gcd", "input", "int", "integer", "lcm", "let", "list", "ln", "lnfact", "log", "max", "min", "mod", "ncr", "pi", "prime", "print", "quit", "rand", "rem", "rnd", "sgn", "sin", "sinh", "sqr", "sqrt", "tan", "tanh".

Eighty eight reserved words in all, forty four in lower and forty four in upper case.

Have fun!

Queries, curses, praise to:

Martin Carradus, Leaf Mindcraft, c/o 27 Wells Road, Ilkley, West Yorkshire, LS29 9JE.

Send s.a.e. if you require a reply.

NB. Please read the Text file !ReadMe within this application for conditions of use. (Hold down 'Shift' and double click with the Mouse over the !MFCalc icon to find it.)

Martin Carradus July 2004.

 Index